home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / MBUF < prev    next >
Text File  |  1994-02-26  |  12KB  |  465 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7.  
  8. struct mbuf *ready_mbuf = NULL;
  9.  
  10. /* Allocate mbuf with associated buffer of 'size' bytes */
  11. struct mbuf *alloc_mbuf(register int size)
  12. {
  13.   register struct mbuf *bp, *lbp = NULL;
  14.  
  15.   if (size > 0 && ready_mbuf != NULL)
  16.   {
  17.     for (bp = ready_mbuf; bp != NULL; lbp = bp, bp = bp->next)
  18.     {
  19.       if (bp->size >= size)
  20.       {
  21.         if (lbp == NULL)
  22.           ready_mbuf = bp->next;
  23.         else
  24.           lbp->next  = bp->next;
  25.         bp->next = bp->anext = NULLBUF;
  26.         bp->cnt  = 0;
  27.         return(bp);
  28.       }
  29.     }
  30.   }
  31.  
  32.   if ((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  33.     return NULLBUF;
  34.   bp->next = bp->anext = NULLBUF;
  35.   if (size != 0)
  36.   {
  37.     bp->data = (char *)(bp + 1);
  38.   }
  39.   else
  40.   {
  41.     bp->data = NULLCHAR;
  42.   }
  43.   bp->size = size;
  44.   bp->cnt = 0;
  45.   return bp;
  46. }
  47.  
  48. /* Free all resources associated with mbuf
  49.    Return pointer to next mbuf in packet chain */
  50. struct mbuf *free_mbuf(register struct mbuf *bp)
  51. {
  52.   register struct mbuf *bp1 = NULLBUF;
  53.  
  54.   if (bp != NULLBUF)
  55.   {
  56.     bp1 = bp->next;
  57.     if (bp->size > 0 && bp->data >= (char *)(bp + 1) && bp->data <= ((char *) bp) + bp->size + sizeof(struct mbuf))
  58.     {
  59.       bp->data   = (char *)(bp + 1);
  60.       bp->next   = ready_mbuf;
  61.       bp->anext  = NULLBUF;
  62.       ready_mbuf = bp;
  63.     }
  64.     else
  65.     {
  66.       free((char *)bp);
  67.     }
  68.   }
  69.   return bp1;
  70. }
  71.  
  72. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  73.    if any */
  74. struct mbuf *free_p(register struct mbuf *bp)
  75. {
  76.         struct mbuf *abp;
  77.  
  78.         if(bp == NULLBUF)
  79.                 return NULLBUF;
  80.         abp = bp->anext;
  81.         while(bp != NULLBUF)
  82.                 bp = free_mbuf(bp);
  83.         return abp;
  84. }               
  85. /* Free entire queue of packets (of mbufs) */
  86. void free_q(struct mbuf **q)
  87. {
  88.         register struct mbuf *bp;
  89.  
  90.         while((bp = dequeue(q)) != NULLBUF)
  91.                 free_p(bp);
  92. }
  93.  
  94. /* Count up the total number of bytes in an mbuf */
  95. int len_mbuf(register struct mbuf *bp)
  96. {
  97.         int cnt;
  98.  
  99.         cnt = 0;
  100.         while(bp != NULLBUF)
  101.         {
  102.                 cnt += bp->cnt;
  103.                 bp = bp->next;
  104.         }
  105.         return cnt;
  106. }
  107. /* Count up the number of packets in a queue */
  108. int len_q(register struct mbuf *bp)
  109. {
  110.         register int cnt;
  111.  
  112.         for (cnt = 0;bp != NULLBUF; cnt++, bp = bp->anext)
  113.           ;
  114.         return cnt;
  115. }
  116. /* Trim mbuf to specified length by lopping off end */
  117. void trim_mbuf(struct mbuf **bpp, int length)
  118. {
  119.         register int tot = 0;
  120.         register struct mbuf *bp;
  121.  
  122.         if(bpp == NULLBUFP || *bpp == NULLBUF)
  123.                 return; /* Nothing to trim */
  124.  
  125.         if(length == 0)
  126.         {
  127.                 /* Toss the whole thing */
  128.                 free_p(*bpp);
  129.                 *bpp = NULLBUF;
  130.                 return;
  131.         }
  132.         /* Find the point at which to trim. If length is greater than
  133.          * the packet, we'll just fall through without doing anything
  134.          */
  135.         for( bp = *bpp; bp != NULLBUF; bp = bp->next)
  136.         {
  137.                 if(tot + bp->cnt < length)
  138.                 {
  139.                         tot += bp->cnt;
  140.                 }
  141.                 else
  142.                 {
  143.                         /* Cut here */
  144.                         bp->cnt = length - tot;
  145.                         free_p(bp->next);
  146.                         bp->next = NULLBUF;
  147.                         break;
  148.                 }
  149.         }
  150. }
  151. /* Duplicate/enqueue/dequeue operations based on mbufs */
  152.  
  153. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  154.  * This is done without copying data; only the headers are duplicated,
  155.  * but without data segments of their own. The pointers are set up to
  156.  * share the data segments of the original copy. The return pointer is
  157.  * passed back through the first argument, and the return value is the
  158.  * number of bytes actually duplicated.
  159.  */
  160. int dup_p(struct mbuf **hp, register struct mbuf *bp,
  161.             register int offset, register int cnt)
  162. {
  163.         register struct mbuf *cp;
  164.         int tot;
  165.  
  166.         if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  167.                 if(hp != NULLBUFP)
  168.                         *hp = NULLBUF;
  169.                 return 0;
  170.         }
  171.         if((*hp = cp = alloc_mbuf(0)) == NULLBUF)
  172.         {
  173.                 return 0;
  174.         }
  175.         /* Skip over leading mbufs that are smaller than the offset */
  176.         while(bp != NULLBUF && bp->cnt <= offset)
  177.         {
  178.                 offset -= bp->cnt;
  179.                 bp = bp->next;
  180.         }
  181.         if (bp == NULLBUF)
  182.         {
  183.                 free_mbuf(cp);
  184.                 *hp = NULLBUF;
  185.                 return 0;       /* Offset was too big */
  186.         }
  187.         tot = 0;
  188.         for(;;)
  189.         {
  190.                 cp->data = bp->data + offset;
  191.                 cp->cnt = min(cnt,bp->cnt - offset);
  192.                 offset = 0;
  193.                 cnt -= cp->cnt;
  194.                 tot += cp->cnt;
  195.                 bp = bp->next;
  196.                 if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  197.                         break;
  198.                 cp = cp->next;
  199.         }
  200.         return tot;
  201. }
  202. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  203. struct mbuf *copy_p(register struct mbuf *bp, register int cnt)
  204. {
  205.         register struct mbuf *cp;
  206.         register char *wp;
  207.         register int n;
  208.  
  209.         if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  210.                 return NULLBUF;
  211.         wp = cp->data;
  212.         while(cnt != 0 && bp != NULLBUF)
  213.         {
  214.                 n = min(cnt, bp->cnt);
  215.                 memcpy(wp, bp->data, n);
  216.                 wp += n;
  217.                 cp->cnt += n;
  218.                 cnt -= n;
  219.                 bp = bp->next;
  220.         }
  221.         return cp;
  222. }
  223.  
  224. int pullone(struct mbuf **bph, char *buf)
  225. {
  226.   register struct mbuf *bp;
  227.  
  228.   if (bph == NULL || *bph == NULL)
  229.     return(0);
  230.  
  231.   bp   = *bph;
  232.   *buf = *bp->data;
  233.   (bp->data)++;
  234.  
  235.   if (--(bp->cnt) == 0)
  236.   {
  237.     if (bp->next == NULL && bp->anext != NULL)
  238.     {
  239.       *bph = bp->anext;
  240.       free_mbuf(bp);
  241.     }
  242.     else
  243.     {
  244.       *bph = free_mbuf(bp);
  245.     }
  246.   }
  247.   return(1);
  248. }
  249.  
  250. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  251.    bytes actually pulled off */
  252. int pullup(struct mbuf **bph, char *buf, int cnt)
  253. {
  254.   register struct mbuf *bp;
  255.   int n, tot = 0;
  256.  
  257.   if (bph == NULL)
  258.     return 0;
  259.   while (*bph != NULL && cnt != 0)
  260.   {
  261.     bp = *bph;
  262.     n  = min(cnt, bp->cnt);
  263.     if (buf != NULL && n != 0)
  264.     {
  265.       if (n == 1)  /* Common case optimization */
  266.         *buf = *bp->data;
  267.       else if(n > 1)
  268.         memcpy(buf, bp->data, n);
  269.       buf += n;
  270.     }
  271.     tot += n;
  272.     cnt -= n;
  273.     bp->data += n;
  274.     bp->cnt  -= n;           
  275.     if (bp->cnt == 0)
  276.     {
  277.       /* If this is the last mbuf of a packet but there
  278.        * are others on the queue, return a pointer to
  279.        * the next on the queue. This allows pullups to
  280.        * to work on a packet queue
  281.        */
  282.       if (bp->next == NULL && bp->anext != NULL)
  283.       {
  284.         *bph = bp->anext;
  285.         free_mbuf(bp);
  286.       }
  287.       else
  288.       {
  289.         *bph = free_mbuf(bp);
  290.       }
  291.     }
  292.   }
  293.   return tot;
  294. }
  295. /* Append mbuf to end of mbuf chain */
  296. void append(struct mbuf **bph, struct mbuf *bp)
  297. {
  298.         register struct mbuf *p;
  299.  
  300.         if(bph == NULLBUFP || bp == NULLBUF)
  301.                 return;
  302.         if(*bph == NULLBUF){
  303.                 /* First one on chain */
  304.                 *bph = bp;
  305.         }
  306.         else
  307.         {
  308.                 for(p = *bph ; p->next != NULLBUF ; p = p->next)
  309.                         ;
  310.                 p->next = bp;
  311.         }
  312. }
  313. /* Insert specified amount of contiguous new space at the beginning of an
  314.  * mbuf chain. If enough space is available in the first mbuf, no new space
  315.  * is allocated. Otherwise a mbuf of the appropriate size is allocated and
  316.  * tacked on the front of the chain.
  317.  *
  318.  * This operation is the logical inverse of pullup(), hence the name.
  319.  */
  320. struct mbuf *pushdown(register struct mbuf *bp, int size)
  321. {
  322.         register struct mbuf *nbp;
  323.  
  324.         /* Check that bp is real and that there's data space associated with
  325.          * this buffer (i.e., this is not a buffer from dup_p) before
  326.          * checking to see if there's enough space at its front
  327.          */
  328.         if(bp != NULLBUF && bp->size != 0 && bp->data - (char *)(bp+1) >= size)
  329.         {
  330.                 /* No need to alloc new mbuf, just adjust this one */
  331.                 bp->data -= size;
  332.                 bp->cnt += size;
  333.         }
  334.         else
  335.         {
  336.                 if ((nbp = alloc_mbuf(size)) != NULLBUF)
  337.                 {
  338.                         nbp->next = bp;
  339.                         nbp->cnt = size;
  340.                         bp = nbp;
  341.                 }
  342.                 else
  343.                 {
  344.                         bp = NULLBUF;
  345.                 }
  346.         }
  347.         return bp;
  348. }
  349. /* Append packet to end of packet queue */
  350. void enqueue(struct mbuf **q, struct mbuf *bp)
  351. {
  352.         register struct mbuf *p;
  353.  
  354.         if(q == NULLBUFP || bp == NULLBUF)
  355.                 return;
  356.         if(*q == NULLBUF){
  357.                 /* List is empty, stick at front */
  358.                 *q = bp;
  359.         } else {
  360.                 for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  361.                         ;
  362.                 p->anext = bp;
  363.         }
  364. }
  365. /* Unlink a packet from the head of the queue */
  366. struct mbuf *dequeue(register struct mbuf **q)
  367. {
  368.         register struct mbuf *bp;
  369.  
  370.         if(q == NULLBUFP)
  371.                 return NULLBUF;
  372.         if((bp = *q) != NULLBUF){
  373.                 *q = bp->anext;
  374.                 bp->anext = NULLBUF;
  375.         }
  376.         return bp;
  377. }       
  378.  
  379. /* Copy user data into an mbuf */
  380. struct mbuf *qdata(char *data, int cnt)
  381. {
  382.         register struct mbuf *bp;
  383.  
  384.         if((bp = alloc_mbuf(cnt)) == NULLBUF)
  385.                 return NULLBUF;
  386.         memcpy(bp->data, data, cnt);
  387.         bp->cnt = cnt;
  388.         return bp;
  389. }
  390. /* Copy mbuf data into user buffer */
  391. int dqdata(struct mbuf *bp, char *buf, unsigned cnt)
  392. {
  393.         unsigned n,tot;
  394.         struct mbuf *bp1;
  395.  
  396.         if(buf == NULLCHAR)
  397.                 return 0;
  398.         
  399.         tot = 0;
  400.         for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  401.                 n = min(bp1->cnt,cnt);
  402.                 memcpy(buf,bp1->data,n);
  403.                 cnt -= n;
  404.                 buf += n;
  405.                 tot += n;
  406.         }
  407.         free_p(bp);
  408.         return tot;
  409. }
  410. /* Pull a 32-bit integer in host order from buffer in network byte order */
  411. int32 pull32(struct mbuf **bpp)
  412. {
  413.         int32 rval;
  414.         char buf[4];
  415.         register char *cp;
  416.  
  417.         if (pullup(bpp, buf, 4) != 4)
  418.         {
  419.                 /* Return zero if insufficient buffer */
  420.                 return 0;
  421.         }
  422.         cp = buf;
  423.  
  424.         /* Unwound for speed */
  425.         rval = uchar(*cp++);
  426.         rval <<= 8;
  427.         rval |= uchar(*cp++);
  428.         rval <<= 8;
  429.         rval |= uchar(*cp++);
  430.         rval <<= 8;
  431.         rval |= uchar(*cp);
  432.  
  433.         return rval;
  434. }
  435. /* Pull a 16-bit integer in host order from buffer in network byte order */
  436. int pull16(struct mbuf **bpp)
  437. {
  438.         int rval;
  439.         char buf[2];
  440.         register char *cp;
  441.  
  442.         if (pullup(bpp, buf, 2) != 2)
  443.         {
  444.                 /* Return zero if insufficient buffer */
  445.                 return 0;
  446.         }
  447.         cp = buf;
  448.  
  449.         rval = *cp++;
  450.         rval <<= 8;
  451.         rval |= *cp;
  452.         return rval;
  453. }
  454. /* Pull single character from mbuf */
  455. char pullchar(struct mbuf **bpp)
  456. {
  457.         char c;
  458.  
  459.         if (pullone(bpp, &c) != 1)
  460.                 /* Return zero if nothing left */
  461.                 c = 0;
  462.         return c;
  463. }
  464.  
  465.